{*****************************Version: MPL 1.1*********************************
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Initial Developer : Fajar Khairil
*
* Portions created by the Initial Developer are Copyright (C) 2010 - 2011
* the Initial Developer. All Rights Reserved.
*
*******************************************************************************
* This File is Part of HdFramework OPF Library
* Copyright (C) 2010 - 2011 HdFramework Developer Team
*
* Unit : hadesqldbconnection
* Description : SQLDB base Connection Service.
* Author: - Fajar Khairil
******************************************************************************}
{ unit visibility : Private,don't use directly if you don't know what you do }
unit hadesqldbconnection;

{$mode objfpc}{$H+}

interface

uses
  Classes,
  SysUtils,
  hadebaseconnection,
  sqldb,
  DB;

type

  { THadeSQLDBConnection }
  {* SQLDB Connection Service
   * Base Class for SQLDB Connection(TIBConnection,TPQConnection etc..)
   * Connect and Disconnect are tied to transaction,
   * client not needed to manage connection itself. }
  THadeSQLDBConnection = class(THadeBaseConnection, IHadeConnection)
  protected
    //share resource with all descendant
    FConnection: TSQLConnection;
    FTransaction: TSQLTransaction;
    function getParams: TStrings;
    procedure setParams(AValue: TStrings);
  public
    constructor Create; virtual;
    destructor Destroy; override;

    //we not needed to implement connection configuration
    //like database,host,username,password
    //because configuration connection
    //already implemented at parent class(THadeBaseConnection)
    procedure Connect;
    procedure Disconnect;

    Procedure setDataSet(Const ADataSet:Pointer);

    procedure ExecuteDirect(const ASql: string);
    function IsConnected: boolean;

    procedure StartTransaction;
    procedure Commit;
    procedure Rollback;
  end;

  {* for all connection of SQLDB we just need to override
   * constructor method }

  { THadeIBConnection }

  THadeIBConnection = class(THadeSQLDBConnection)
  public
    constructor Create; override;
  end;

  { THadeMySQLConnection }

  THadeMySQLConnection = class(THadeSQLDBConnection)
  public
    constructor Create; override;
  end;

  { THadePostgreConnection }

  THadePostgreConnection = class(THadeSQLDBConnection)
  public
    constructor Create; override;
  end;

  { THadeSQLiteConnection }

  THadeSQLiteConnection = class(THadeSQLDBConnection)
  public
    constructor Create; override;
    function getLastInsertID(ATableName:String):int64;
  end;

  { THadeOracleConnection }

  THadeOracleConnection = class(THadeSQLDBConnection)
  public
    constructor Create; override;
  end;

  { THadeODBCConnection }

  THadeODBCConnection = class(THadeSQLDBConnection)
  public
    constructor Create; override;
  end;
implementation

uses
  hadeexception,
  IBConnection,
  pqconnection,
  oracleconnection,
  sqlite3conn,
  mysql51conn,
  odbcconn;

{ THadeODBCConnection }

constructor THadeODBCConnection.Create;
begin
  FConnection := TODBCConnection.Create(nil);
  inherited Create;
end;

{ THadeSQLDBConnection }

function THadeSQLDBConnection.getParams: TStrings;
begin
  Result := FConnection.Params;
end;

procedure THadeSQLDBConnection.setParams(AValue: TStrings);
begin
  FConnection.Params:=AValue;
end;

constructor THadeSQLDBConnection.Create;
begin
  FTransaction := TSQLTransaction.Create(nil);
  FConnection.KeepConnection := False;
  FConnection.Transaction := FTransaction;
  FTransaction.DataBase := FConnection;
  FTransaction.Active:=False;
end;

destructor THadeSQLDBConnection.Destroy;
begin
  FreeAndNil(FTransaction);
  //disconnect first
  self.Disconnect;
  FreeAndNil(FConnection);
  inherited Destroy;
end;

procedure THadeSQLDBConnection.setDataSet(const ADataSet: Pointer);
begin
  TSQLQuery(ADataSet).DataBase:=self.FConnection;
end;

procedure THadeSQLDBConnection.ExecuteDirect(const ASql: string);
begin
  try
    FConnection.ExecuteDirect(ASql);
  except
    on E: EDatabaseError do
      raise EHadeDatabase.Create(E.Message);
  end;
end;

function THadeSQLDBConnection.IsConnected: boolean;
begin
  Result := FConnection.Connected;
end;

procedure THadeSQLDBConnection.Connect;
begin
  FConnection.DatabaseName := Self.Database;
  FConnection.HostName := Self.Host;
  FConnection.UserName := Self.Username;
  FConnection.Password := Self.Password;

  if not self.IsConnected then
  begin
    try
      FConnection.Connected := True;
    except
      on E: EDatabaseError do
        raise EHadeDatabase.Create(E.Message);
    end;
  end;
end;


procedure THadeSQLDBConnection.Disconnect;
begin
  if self.IsConnected then
    FConnection.Connected := False;
end;

procedure THadeSQLDBConnection.StartTransaction;
begin
  Try
    FTransaction.StartTransaction;
  except
    on E: EDatabaseError do
      raise EHadeDatabase.Create(E.Message);
  end;
end;

procedure THadeSQLDBConnection.Commit;
begin
  try
    FTransaction.Action := caCommit;
    FTransaction.Commit;
    FTransaction.active := False;
  except
    on E: EDatabaseError do
      raise EHadeDatabase.Create(E.Message);
  end;
end;

procedure THadeSQLDBConnection.Rollback;
begin
  try
    FTransaction.Action := caRollback;
    FTransaction.Rollback;
    FTransaction.active := False;
  except
    on E: EDatabaseError do
      raise EHadeDatabase.Create(E.Message);
  end;
end;

{ THadePostgreConnection }

constructor THadePostgreConnection.Create;
begin
  FConnection := TPQConnection.Create(nil);
  inherited Create;//call parent constructor
end;

{ THadeSQLiteConnection }

constructor THadeSQLiteConnection.Create;
begin
  FConnection := TSQLite3Connection.Create(nil);
  inherited Create;//call parent constructor
end;

function THadeSQLiteConnection.getLastInsertID(ATableName: String): int64;
begin
  Result:= TSQLite3Connection(FConnection).GetInsertID;
end;

{ THadeOracleConnection }

constructor THadeOracleConnection.Create;
begin
  FConnection := TOracleConnection.Create(nil);
  inherited Create;//call parent constructor
end;

{ THadeMySQLConnection }

constructor THadeMySQLConnection.Create;
begin
  FConnection := TMySQL51Connection.Create(nil);
  inherited Create;//call parent constructor
end;

{ THadeIBConnection }

constructor THadeIBConnection.Create;
begin
  FConnection := TIBConnection.Create(nil);
  inherited Create;//call parent constructor
end;

end.

